package com.lyq.bean.service;

import com.lyq.bean.Course;
import java.util.*;

public class ScheduleService {
    
    // 课程安排结果类
    public static class ScheduleResult {
        private List<Course> scheduledCourses;
        private List<String> conflicts;
        private boolean success;
        
        public ScheduleResult(List<Course> scheduledCourses, List<String> conflicts, boolean success) {
            this.scheduledCourses = scheduledCourses;
            this.conflicts = conflicts;
            this.success = success;
        }
        
        public List<Course> getScheduledCourses() {
            return scheduledCourses;
        }
        
        public List<String> getConflicts() {
            return conflicts;
        }
        
        public boolean isSuccess() {
            return success;
        }
    }
    
    /**
     * 使用贪心算法安排课程
     * @param courses 待安排的课程列表
     * @param existingCourses 已选课程列表
     * @return 安排结果
     */
    public ScheduleResult scheduleCourses(List<Course> courses, List<Course> existingCourses) {
        List<Course> scheduledCourses = new ArrayList<>();
        List<String> conflicts = new ArrayList<>();
        
        // 合并已选课程和待安排课程
        List<Course> allCourses = new ArrayList<>();
        allCourses.addAll(existingCourses);
        allCourses.addAll(courses);
        
        // 按照课程学分排序（优先安排学分高的课程）
        allCourses.sort((c1, c2) -> {
            try {
                double credit1 = Double.parseDouble(c1.getCredit());
                double credit2 = Double.parseDouble(c2.getCredit());
                return Double.compare(credit2, credit1);
            } catch (NumberFormatException e) {
                return 0;
            }
        });
        
        // 贪心算法：依次尝试安排每门课程
        List<Course> finalSchedule = new ArrayList<>();
        for (Course course : allCourses) {
            if (canAddCourse(course, finalSchedule)) {
                finalSchedule.add(course);
            } else {
                // 检查是否是新添加的课程
                if (courses.contains(course) && !existingCourses.contains(course)) {
                    conflicts.add("课程 " + course.getName() + " (" + course.getNo() + ") 与其他课程时间冲突");
                }
            }
        }
        
        // 检查是否所有新课程都安排成功
        boolean allScheduled = true;
        for (Course course : courses) {
            if (!finalSchedule.contains(course)) {
                allScheduled = false;
                break;
            }
        }
        
        return new ScheduleResult(finalSchedule, conflicts, allScheduled);
    }
    
    /**
     * 检查课程是否可以添加到当前课表中
     * @param course 待添加的课程
     * @param currentSchedule 当前课表
     * @return 是否可以添加
     */
    private boolean canAddCourse(Course course, List<Course> currentSchedule) {
        // 线上课程不会产生时间冲突
        if ("线上".equals(course.getCourseType())) {
            return true;
        }
        
        // 检查与课表中每门课程的时间冲突
        for (Course scheduledCourse : currentSchedule) {
            if (isTimeConflict(course, scheduledCourse)) {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 检查两门课程是否时间冲突
     * @param course1 课程1
     * @param course2 课程2
     * @return 是否冲突
     */
    private boolean isTimeConflict(Course course1, Course course2) {
        // 如果任一课程是线上课程，则不冲突
        if ("线上".equals(course1.getCourseType()) || "线上".equals(course2.getCourseType())) {
            return false;
        }
        
        String time1 = course1.getTime();
        String time2 = course2.getTime();
        
        // 如果时间信息不完整，则无法判断冲突
        if (time1 == null || time1.isEmpty() || time2 == null || time2.isEmpty()) {
            return false;
        }
        
        // 解析时间格式
        TimeSlot slot1 = parseTimeSlot(time1);
        TimeSlot slot2 = parseTimeSlot(time2);
        
        if (slot1 == null || slot2 == null) {
            return false;
        }
        
        // 检查星期是否相同
        if (!slot1.day.equals(slot2.day)) {
            return false;
        }
        
        // 检查时间是否重叠
        return isTimeOverlap(slot1.startTime, slot1.endTime, slot2.startTime, slot2.endTime);
    }
    
    // 时间段类
    private static class TimeSlot {
        String day;
        int startTime; // 以分钟表示的时间（从0:00开始）
        int endTime;
        
        TimeSlot(String day, int startTime, int endTime) {
            this.day = day;
            this.startTime = startTime;
            this.endTime = endTime;
        }
    }
    
    // 解析时间字符串
    private TimeSlot parseTimeSlot(String timeStr) {
        try {
            // 示例格式："周一 8:00-10:00"
            String[] parts = timeStr.trim().split(" ");
            if (parts.length < 2) {
                return null;
            }
            
            String day = parts[0];
            String timePart = parts[1];
            
            String[] timeRange = timePart.split("-");
            if (timeRange.length != 2) {
                return null;
            }
            
            int startTime = parseTime(timeRange[0]);
            int endTime = parseTime(timeRange[1]);
            
            if (startTime == -1 || endTime == -1) {
                return null;
            }
            
            return new TimeSlot(day, startTime, endTime);
        } catch (Exception e) {
            return null;
        }
    }
    
    // 将时间字符串（如"8:00"）转换为分钟数
    private int parseTime(String timeStr) {
        try {
            String[] parts = timeStr.split(":");
            int hours = Integer.parseInt(parts[0]);
            int minutes = Integer.parseInt(parts[1]);
            return hours * 60 + minutes;
        } catch (Exception e) {
            return -1;
        }
    }
    
    // 检查两个时间段是否重叠
    private boolean isTimeOverlap(int start1, int end1, int start2, int end2) {
        // 两个时间段重叠的条件：一个时间段的开始时间小于另一个时间段的结束时间，
        // 且一个时间段的结束时间大于另一个时间段的开始时间
        return start1 < end2 && start2 < end1;
    }
    
    /**
     * 使用回溯算法寻找最优课程安排（适用于复杂场景）
     * @param courses 待安排的课程列表
     * @param existingCourses 已选课程列表
     * @return 最优安排结果
     */
    public ScheduleResult findOptimalSchedule(List<Course> courses, List<Course> existingCourses) {
        // 这里可以实现更复杂的回溯算法或遗传算法
        // 为了简化，我们暂时使用贪心算法
        return scheduleCourses(courses, existingCourses);
    }
}